/*
 * Copyright (c) 2001, 2002 Boris Pruessmann and others. All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Common Public License v0.5 which accompanies this distribution,
 * and is available at http://www.eclipse.org/legal/cpl-v05.html
 *
 * Contributors: Boris Pruessmann - Initial implementation.
 */
package net.sourceforge.perforce.api.internal;

import net.sourceforge.perforce.api.CharSetEnum;
import net.sourceforge.perforce.api.IClientApi;
import net.sourceforge.perforce.api.IPerforceCommand;
import net.sourceforge.perforce.api.PerforceApiPlugin;
import net.sourceforge.perforce.api.Policy;

/**
 * Wrapper class for Perforce API ClientApi class.
 *
 * @version $Revision: 491 $
 * @author <a href="mailto:bpruessmann@users.sourceforge.net>Boris
 *         Pruessmann</a>
 */
public final class ClientApi implements IClientApi {

  /**
   * Used to store the native reference. <br>
   * DON'T TOUCH THE CONTENT OF THIS VARIABLE
   */
  @SuppressWarnings("unused")
  private int _nativeHandle;

  /** Stores an instance of Error used during init and dispose. */
  private Error error;

  /** Constructor for ClientApi. */
  public ClientApi() {
    construct();
  }

  public void init(CharSetEnum charSet) {
    error = new Error();

    if (charSet != CharSetEnum.NOCONV) {
      final int utf8 = CharSetEnum.UTF_8.getId();
      setTrans(utf8, charSet.getId(), utf8, utf8);
    }

    init(error);
  }


  public int dispose() {
    int result = dispose(error);
    destruct();

    error.dispose();
    error = null;

    return result;
  }

  public synchronized void run(String[] arguments, IPerforceCommand delegate) {
    long start = System.currentTimeMillis();

    ClientUser clientUser = new ClientUser(delegate);
    try {
      setArguments(arguments);
      run(delegate.getCommand(), clientUser);
    } finally {
      clientUser.dispose();
    }

    long stop = System.currentTimeMillis();
    if (PerforceApiPlugin.getPlugin().isDebugging()) {
      Object[] values = new Object[] { delegate.getCommand(), new Long(stop - start) };

      StringBuilder message = new StringBuilder(Policy.bind("ClientApi.run", values));
      if (arguments.length > 0) {
        message.append(" [Arguments: ");
        for (int i = 0; i < arguments.length; i++) {
          message.append(arguments[i].toString());
          if (i < arguments.length - 1) {
            message.append(", ");
          }
        }
        message.append("]");
      }

      System.out.println(message.toString()); //$NON-NLS-1$
    }
  }

  public native boolean dropped();

  public native void setPort(String serverNameAndPort);

  public native String getPort();

  public native void setClient(String client);

  public native String getClient();

  public native void setUser(String user);

  public native String getUser();

  public native void setProtocol(String key, String value);

  public native String getCharset();

  public native void setCharset(String charset);

  public native String getHost();

  public native void setHost(String host);

  public native String getLanguage();

  public native void setLanguage(String language);

  public native String getPassword();

  public native void setPassword(String password);

  public native String getProtocol(String key);

  public native String getCwd();

  public native void setCwd(String cwd);

  public Error getPerforceError() {
    return error;
  }

  /**
   * Wrapper for ClientApi::SetTrans.
   *
   * @param output translation of message output and input arguments.
   * @param content translation of unicode file contents.
   * @param fnames translation of file system path names.
   * @param dialog translation of form specification dialogs.
   */
  private native void setTrans(int output, int content, int fnames, int dialog);

  /**
   * Wrapper for ClientApi::Init.
   *
   * @param error instance of Error used for error submission.
   */
  private native void init(Error error);

  /**
   * Wrapper for ClientApi::SetArgv.
   *
   * @param arguments arguments for the next command to execute.
   */
  private native void setArguments(String[] arguments);

  /**
   * Wrapper for ClientApi::Run.
   *
   * @param function name of the perforce command.
   * @param clientUser IClientUser instance used for interaction.
   */
  private native void run(String function, ClientUser clientUser);

  /**
   * Wrapper for ClientApi::Final.
   *
   * @param error instance of Error used for error submission.
   * @return result code.
   */
  private native int dispose(Error error);

  /**
   * Called by the constructor to initialize the native side of this class.
   */
  private native void construct();

  /**
   * Called by dispose() to destroy the native side of this class.
   */
  private native void destruct();

}
